﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Lesk;
using Infinity.ExpressionParser.Tokens;
using Infinity.ExpressionParser.Tokens.Separators;
using Infinity.ExpressionParser.Tokens.Operators.Binary;
using Infinity.ExpressionParser.Tokens.Operators.Quantifier;
using Infinity.ExpressionParser.Tokens.Operators.Unary;

namespace Infinity.ExpressionParser
{
	public class Tokenizer : ITokenizer
	{
		protected LeskInstance.LeskBuilder instance;

		public Tokenizer()
		{
			instance = LeskInstance.Configure;

			instance.DefineToken(@":=", () => new AssignmentToken()).
					 DefineToken("\".*?\"", () => new StringValueToken()).
					 DefineToken(@"((?<=[^0-9\)])-)?[0-9]+", () => new IntegerValueToken()).
					 DefineToken(@"((?<=[^0-9\)])[-\+])?(([0-9]+\.[0-9]*)|([0-9]*\.[0-9]+))", () => new DoubleValueToken()).
					 DefineToken(@"\+", () => new AdditiveToken()).
					 DefineToken(@"\*", () => new MultiplicativeToken()).
					 DefineToken(@"-", () => new SubstractToken()).
					 DefineToken(@"/", () => new DivideToken()).
					 DefineToken(@"\^", () => new PowerToken()).
					 DefineToken(@"and", () => new AndToken()).
					 DefineToken(@"or", () => new OrToken()).
					 DefineToken(@"not", () => new NotToken()).
					 DefineToken(@"union", () => new UnionToken()).
					 DefineToken(@"minus", () => new ExceptToken()).
					 DefineToken(@"intersect", () => new IntersectToken()).
					 DefineToken(@"in", () => new InToken()).
					 DefineToken(@"subset", () => new SubsetToken()).
					 DefineToken(@"superset", () => new SupersetToken()).
					 DefineToken(@"\{\}", () => new EmptySetValueToken()).
					 DefineToken(@"<", () => new LessThanToken()).
					 DefineToken(@"<=", () => new LessThanOrEqualToken()).
					 DefineToken(@">", () => new GreaterThanToken()).
					 DefineToken(@">=", () => new GreaterThanOrEqualToken()).
					 DefineToken(@"==", () => new EqualToken()).
					 DefineToken(@"!=", () => new NotEqualToken()).
					 DefineToken(@"=>", () => new ImplicationToken()).
					 DefineToken(@"<=>", () => new EquivalenceToken()).
					 DefineToken(@"false|true", () => new LogicalValueToken()).
					 DefineToken(@"\(", () => new OpenRegularBracketToken()).
					 DefineToken(@"\[", () => new OpenIndexerBracketToken()).
					 DefineToken(@"\{", () => new OpenSetBracketToken()).
					 DefineToken(@"\)", () => new CloseRegularBracketToken()).
					 DefineToken(@"\]", () => new CloseIndexerBracketToken()).
					 DefineToken(@"\}", () => new CloseSetBracketToken()).
					 DefineToken(@",", () => new CommaSeparatorToken()).
					 DefineToken(@":|\|", () => new ColonOperatorToken()).
					 DefineToken(@"forall\s+([_a-zA-Z][\w]*)\s+in", () => new ForAllToken()).
					 DefineToken(@"exists\s+([_a-zA-Z][\w]*)\s+in", () => new ExistsToken()).
					 //DefineToken(@"\.", () => new DotSeparatorToken()).
					 DefineToken(@"[_a-zA-Z][\w]*", () => new IdentifierToken()).
					 DefineToken(@"\s+", () => new WhiteSpaceToken());
		}

		public List<Token> Tokenize(string input)
		{
			return instance.AsCompiled().Done().Tokenize(input);
		}
	}
}
